﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using SQMarketApiWrapper;
using System.Threading;
using System.Collections.Concurrent;
using CTP.Entitys;
using CTP.Session;
using CTP.Utilty;
using CTP.Exceptions;

namespace CTP.Session
{
    /// <summary>
    /// 功能：QouteSession的作用是提供客户系统接口与上期行情API之间的连接及对话功能。
    ///       QouteSession接收对外接口中传递进来的命令，按照命令的类型，发送到上期行情API相应的接口中
    /// 创建：陈粤雄 20120607
    /// </summary>
    public class QouteSession : CThostFtdcMdSpiWrapper, IDisposable
    {
        #region 字段
        private CThostFtdcMdApiWrapper sqApi = null;
        private ManualResetEvent m_connectEvent = new ManualResetEvent(false);
        private List<string> m_subCodeCache = new List<string>();
        #endregion

        #region 属性
        /// <summary>
        /// 获取当前会话状态(线程安全)
        /// </summary>
        public bool IsConnected
        {
            get { lock (isConnectedSync) { return isConnected; } }
            private set { lock (isConnectedSync) { isConnected = value; } }
        }
        private bool isConnected = false;
        private object isConnectedSync = new object();

        /// <summary>
        /// 是否已登陆(线程安全)
        /// </summary>
        public bool IsLogined
        {
            get { lock (isLoginedSync) { return isLogined; } }
            private set { lock (isLoginedSync) { isLogined = value; } }
        }
        private bool isLogined = false;
        private object isLoginedSync = new object();

        /// <summary>
        /// 资金账号
        /// </summary>
        public TradingAccount Account { get; private set; }

        /// <summary>
        /// 获取单例
        /// </summary>
        public static QouteSession Instance { get; private set; }
        #endregion

        #region 构造
        /// <summary>
        /// 静态构造
        /// </summary>
        static QouteSession()
        {
            Instance = new QouteSession();
        }

        /// <summary>
        /// 构造行情会话
        /// </summary>
        private QouteSession()
        {
            IsConnected = false;
            IsLogined = false;
            Account = new TradingAccount();
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 初始化API
        /// </summary>
        /// <returns></returns>
        private int initApi()
        {
            try
            {
                // 指定会话文件
                string currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string conFilePath = Path.Combine(currentDir, "ctpcon\\Qoute\\" + Account.UserAccount + "\\");
                if (!Directory.Exists(conFilePath))
                    Directory.CreateDirectory(conFilePath);

                // 初始化API
                sqApi = new CThostFtdcMdApiWrapper(conFilePath);
                sqApi.RegisterSpi(this);
                Logger.Instance.WriteDebug("上期期货行情:sqApi.RegisterSpi(this);");

                sqApi.RegisterFront(Config.Instance.ConnectAddressQoute + ":" + Config.Instance.ConnectPortQoute);
                Logger.Instance.WriteDebug("上期期货行情:sqApi.RegisterFront(frontAddr);");

                sqApi.Init();
                Logger.Instance.WriteDebug("上期期货行情:sqApi.Init();");

                return ErrorCode.Success;
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                return ErrorCode.UnHandle;
            }
        }

        /// <summary>
        /// 连接
        /// </summary>
        private int connectApi()
        {
            Logger.Instance.WriteInfo("上期期货行情开始连接");
            m_connectEvent.Reset();

            // 以新线程连接API，直接收到连接响应或超时
            Thread joinThread = new Thread(new ThreadStart(() =>
                  {
                      try
                      {
                          sqApi.Join();
                      }
                      catch (Exception ex)
                      {
                          string errorStr = string.Format("资金账号：{0} 与上期行情连接失败，原因:{1}", this.Account.UserAccount, ex.Message);
                          Logger.Instance.WriteError(errorStr);
                          Logger.Instance.WriteError(string.Format("资金账号：{0}与上期行情连接失败，正在重新连接...", this.Account.UserAccount));
                          ResponseManager.Instance.OnError(this.Account.UserAccount, ReturnInfo.Create(false, ErrorCode.ConnectFailt), -1);
                      }
                  }));
            joinThread.IsBackground = true;
            joinThread.Start();

            // 阻塞当前线程，直接连接功能或连接超时
            if (!m_connectEvent.WaitOne(5000))
            {
                string errorStr = string.Format("资金账号：{0} 与上期行情连接超时，超过{1}毫秒无响应", this.Account.UserAccount, Config.Instance.ConnectTimeoutQoute);
                Logger.Instance.WriteError(errorStr);
                ResponseManager.Instance.OnError(this.Account.UserAccount, ReturnInfo.Create(false, ErrorCode.ConnectTimeout), -1);
                return ErrorCode.ConnectTimeout;
            }

            return ErrorCode.Success;
        }

        #endregion

        #region 公开方法
        /// <summary>
        /// 登陆
        /// </summary>
        public int Login(TradingAccount account, int requestID)
        {
            try
            {
                // 第一次初始化api
                if (sqApi == null)
                {
                    initApi();
                    int r = connectApi();
                    if (r != ErrorCode.Success)
                        return r;

                    this.Account = account;
                }               
                // 如果已经登陆，则直接返回登陆响应
                else if (IsLogined)
                {
                    Logger.Instance.WriteDebug("上期期货行情账号已经登陆");
                    ResponseManager.Instance.OnLoginQoute(
                        account.UserAccount,
                        ReturnInfo.Create(true, ErrorCode.Success, ""),
                        new LoginInfo() { IsLogined = true, TradingAccount = account.UserAccount },
                        requestID);
                }

                int res = checkState(true);
                if (res != ErrorCode.Success)
                    return res;

                Logger.Instance.WriteDebug("上期期货行情：sqApi.ReqUserLogin(loginReq, ++seq);");
                CThostFtdcReqUserLoginFieldWrapper loginReq = new CThostFtdcReqUserLoginFieldWrapper();
                loginReq.BrokerID = account.BranchNO;
                loginReq.UserID = account.UserAccount;
                loginReq.Password = account.Password;
                sqApi.ReqUserLogin(loginReq, requestID);

            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                ResponseManager.Instance.OnError(Account.UserAccount, returnInfo, requestID);
                return ErrorCode.UnHandle;
            }

            return ErrorCode.Success;
        }

        /// <summary>
        /// 登出
        /// </summary>
        public int Logout(TradingAccount account, int requestID)
        {
            try
            {
                Logger.Instance.WriteDebug("上期期货行情已登出：sqApi.ReqUserLogout(loginReq, requestID);");
                ResponseManager.Instance.OnLogoutQoute(account.UserAccount, ReturnInfo.Create(true, ErrorCode.Success), requestID);
            }
            catch (Exception ex)
            {
                ReturnInfo returnInfo = ReturnInfo.Create(false, ErrorCode.UnHandle, ex.Message);
                ResponseManager.Instance.OnError(Account.UserAccount, returnInfo, requestID);
                return ErrorCode.UnHandle;
            }

            return ErrorCode.Success;
        }

        /// <summary>
        /// 订阅行情
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public int SubscribeQoute(string[] codes)
        {
            try
            {
                int res = checkState(false);
                if (res != ErrorCode.Success)
                    return res;

                // 添加到缓存，以便断开连接后可以重新订阅
                foreach (string code in codes)
                {
                    if (!m_subCodeCache.Exists(p => p == code))
                        m_subCodeCache.Add(code);
                }

                return sqApi.SubscribeMarketData(codes);
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                return ErrorCode.UnHandle;
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public int UnSubscribeQoute(string[] codes)
        {
            try
            {
                int res = checkState(false);
                if (res != ErrorCode.Success)
                    return res;

                // 移除缓存
                foreach (string code in codes)
                {
                    if (m_subCodeCache.Exists(p => p == code))
                        m_subCodeCache.Remove(code);
                }

                return sqApi.UnSubscribeMarketData(codes);
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
                return ErrorCode.UnHandle;
            }
        }

        /// <summary>
        /// 结束会话
        /// </summary>
        public void Dispose()
        {
            try
            {
                Logger.Instance.WriteInfo("上期期货行情停止");
                sqApi.Release();
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 检查当前api状态
        private int checkState(bool isLoginRequest)
        {
            if (!IsConnected)
            {
                string errorStr = string.Format("与上期行情没连接，或连接已断开，或已登出，请等待重新连接或重新登陆");
                Logger.Instance.WriteError(errorStr);
                ResponseManager.Instance.OnError(this.Account.UserAccount, ReturnInfo.Create(false, ErrorCode.UnConnected), -1);

                return ErrorCode.UnConnected;
            }
            else if (!IsLogined && !isLoginRequest)
            {
                string errorStr = string.Format("资金账号未登陆，或连接已断开，请重新登陆");
                Logger.Instance.WriteError(errorStr);
                ResponseManager.Instance.OnError(this.Account.UserAccount, ReturnInfo.Create(false, ErrorCode.UnConnected), -1);

                return ErrorCode.NotLogin;
            }
            else
            {
                return ErrorCode.Success;
            }
        }
        #endregion

        #region CThostFtdcMdSpiWrapper 成员

        // 连接响应
        void CThostFtdcMdSpiWrapper.OnFrontConnected()
        {
            try
            {
                Logger.Instance.WriteInfo("上期期货行情连接成功");
                IsConnected = true;
                m_connectEvent.Set();

                // 如果成功连接过（即是连接断开后的重新连接），且已登陆过，则重新登陆一次
                if (!string.IsNullOrEmpty(Account.UserAccount))
                {
                    Login(Account, 1);
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 连接断开
        void CThostFtdcMdSpiWrapper.OnFrontDisconnected(int nReason)
        {
            try
            {
                Logger.Instance.WriteDebug(string.Format("上期行情连接中断:{0}，正在重连...", nReason));
                IsConnected = false;
                IsLogined = false;
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 心跳
        void CThostFtdcMdSpiWrapper.OnHeartBeatWarning(int nTimeLapse)
        {
            try
            {

                Logger.Instance.WriteDebug(string.Format("上期行情心跳报警:{0}", nTimeLapse));
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 错误
        void CThostFtdcMdSpiWrapper.OnRspError(CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteError(string.Format("上期行情请求出错:{0},{1}", pRspInfo.ErrorID, pRspInfo.ErrorMsg));
                ReturnInfo returnInfo = new ReturnInfo()
                {
                    ErrorCode = pRspInfo.ErrorID,
                    ErrorMessage = pRspInfo.ErrorMsg,
                    IsSuccess = false
                };

                ResponseManager.Instance.OnError(Account.UserAccount, returnInfo, nRequestID);
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 订阅成功
        void CThostFtdcMdSpiWrapper.OnRspSubMarketData(CThostFtdcSpecificInstrumentFieldWrapper pSpecificInstrument, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("上期行情订阅:{0}", pSpecificInstrument.InstrumentID));
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 取消订阅成功
        void CThostFtdcMdSpiWrapper.OnRspUnSubMarketData(CThostFtdcSpecificInstrumentFieldWrapper pSpecificInstrument, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                Logger.Instance.WriteInfo(string.Format("上期行情取消订阅:{0}", pSpecificInstrument.InstrumentID));
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 用户登陆响应
        void CThostFtdcMdSpiWrapper.OnRspUserLogin(CThostFtdcRspUserLoginFieldWrapper pRspUserLogin, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                ReturnInfo returnInfo;
                LoginInfo loginInfo;

                // 登陆成功
                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    IsLogined = true;
                    Logger.Instance.WriteInfo(string.Format("上期期货行情登陆成功，资金账号={0}", pRspUserLogin.UserID));

                    returnInfo = new ReturnInfo()
                    {
                        ErrorCode = ErrorCode.Success,
                        ErrorMessage = pRspInfo != null ? pRspInfo.ErrorMsg : "",
                        IsSuccess = true
                    };

                    loginInfo = new LoginInfo()
                    {
                        IsLogined = true,
                        TradingAccount = pRspUserLogin.UserID
                    };

                    IsLogined = true;

                    // 登陆后重新订阅代码
                    SubscribeQoute(m_subCodeCache.ToArray());
                }
                // 登陆失败
                else
                {
                    Logger.Instance.WriteInfo(string.Format("上期期货行情登陆失败，资金账号={0}，ErrorID={1}，ErrorMsg={2}",
                        pRspUserLogin.UserID,
                        pRspInfo != null ? pRspInfo.ErrorID : 0,
                        pRspInfo != null ? pRspInfo.ErrorMsg : ""));

                    returnInfo = new ReturnInfo()
                    {
                        ErrorCode = ErrorCode.LoginFailt,
                        ErrorMessage = pRspInfo != null ? pRspInfo.ErrorMsg : "",
                        IsSuccess = false
                    };

                    loginInfo = new LoginInfo()
                    {
                        IsLogined = false,
                        TradingAccount = pRspUserLogin.UserID
                    };
                }

                ResponseManager.Instance.OnLoginQoute(pRspUserLogin.UserID, returnInfo, loginInfo, nRequestID);
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 用户登出响应
        void CThostFtdcMdSpiWrapper.OnRspUserLogout(CThostFtdcUserLogoutFieldWrapper pUserLogout, CThostFtdcRspInfoFieldWrapper pRspInfo, int nRequestID, bool bIsLast)
        {
            try
            {
                ReturnInfo returnInfo;

                if (pRspInfo == null || pRspInfo.ErrorID == 0)
                {
                    Logger.Instance.WriteInfo(string.Format("上期期货行情登出成功，资金账号={0}", pUserLogout.UserID));
                    returnInfo = new ReturnInfo()
                    {
                        ErrorCode = ErrorCode.Success,
                        ErrorMessage = pRspInfo != null ? pRspInfo.ErrorMsg : "",
                        IsSuccess = true
                    };

                    IsLogined = false;
                }
                else
                {
                    Logger.Instance.WriteInfo(string.Format("上期期货行情登陆失败，资金账号={0}，ErrorID={1}，ErrorMsg={2}",
                           pUserLogout.UserID,
                           pRspInfo != null ? pRspInfo.ErrorID : 0,
                           pRspInfo != null ? pRspInfo.ErrorMsg : ""));
                    returnInfo = new ReturnInfo()
                    {
                        ErrorCode = ErrorCode.LoginFailt,
                        ErrorMessage = pRspInfo != null ? pRspInfo.ErrorMsg : "",
                        IsSuccess = false
                    };
                }

                ResponseManager.Instance.OnLogoutQoute(pUserLogout.UserID, returnInfo, nRequestID);

            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        // 收到行情
        void CThostFtdcMdSpiWrapper.OnRtnDepthMarketData(CThostFtdcDepthMarketDataFieldWrapper pDepthMarketData)
        {
            try
            {
                Logger.Instance.WriteDebug(string.Format("接收到上期期货行情，Code={0}，Time={1}，LastPrice={2}，Volume={3}",
                    pDepthMarketData.InstrumentID,
                    DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"),
                    pDepthMarketData.LastPrice,
                    pDepthMarketData.Volume
                    ));

                QouteInfo qouteInfo = new QouteInfo();

                #region 行情数据转换
                qouteInfo.Symbol = pDepthMarketData.InstrumentID.ToUpper();
                qouteInfo.Market = pDepthMarketData.ExchangeID;
                qouteInfo.ExchTradeDay = pDepthMarketData.TradingDay;
                qouteInfo.ExchTradeTime = pDepthMarketData.UpdateTime;

                qouteInfo.Amount = pDepthMarketData.Turnover;
                qouteInfo.Volume = (float)pDepthMarketData.Volume;
                qouteInfo.AvgPrice = (float)Math.Round(pDepthMarketData.AveragePrice, 3);
                qouteInfo.Position = (float)Math.Round(pDepthMarketData.OpenInterest, 3);

                qouteInfo.DownLimitPrice = (float)Math.Round(pDepthMarketData.LowerLimitPrice);
                qouteInfo.UpLimitPrice = (float)Math.Round(pDepthMarketData.UpperLimitPrice, 3);

                #region 买价/量 1-5
                if (pDepthMarketData.BidPrice1 > double.MaxValue / 10 || pDepthMarketData.BidPrice1 < double.MinValue / 10)
                {
                    qouteInfo.BuyPrice1 = 0;
                }
                else
                {
                    qouteInfo.BuyPrice1 = (float)Math.Round(pDepthMarketData.BidPrice1, 3);
                }

                if (pDepthMarketData.BidPrice2 > double.MaxValue / 10 || pDepthMarketData.BidPrice2 < double.MinValue / 10)
                {
                    qouteInfo.BuyPrice2 = 0;
                }
                else
                {
                    qouteInfo.BuyPrice2 = (float)Math.Round(pDepthMarketData.BidPrice2, 3);
                }

                if (pDepthMarketData.BidPrice3 > double.MaxValue / 10 || pDepthMarketData.BidPrice3 < double.MinValue / 10)
                {
                    qouteInfo.BuyPrice3 = 0;
                }
                else
                {
                    qouteInfo.BuyPrice3 = (float)Math.Round(pDepthMarketData.BidPrice3, 3);
                }

                if (pDepthMarketData.BidPrice4 > double.MaxValue / 10 || pDepthMarketData.BidPrice4 < double.MinValue / 10)
                {
                    qouteInfo.BuyPrice4 = 0;
                }
                else
                {
                    qouteInfo.BuyPrice4 = (float)Math.Round(pDepthMarketData.BidPrice4, 3);
                }

                if (pDepthMarketData.BidPrice5 > double.MaxValue / 10 || pDepthMarketData.BidPrice5 < double.MinValue / 10)
                {
                    qouteInfo.BuyPrice5 = 0;
                }
                else
                {
                    qouteInfo.BuyPrice5 = (float)Math.Round(pDepthMarketData.BidPrice5, 3);
                }

                qouteInfo.BuyVol1 = (float)pDepthMarketData.BidVolume1;
                qouteInfo.BuyVol2 = (float)pDepthMarketData.BidVolume2;
                qouteInfo.BuyVol3 = (float)pDepthMarketData.BidVolume3;
                qouteInfo.BuyVol4 = (float)pDepthMarketData.BidVolume4;
                qouteInfo.BuyVol5 = (float)pDepthMarketData.BidVolume5;

                #endregion

                #region 卖价/量 1-5
                if (pDepthMarketData.AskPrice1 > double.MaxValue / 10 || pDepthMarketData.AskPrice1 < double.MinValue / 10)
                {
                    qouteInfo.SellPrice1 = 0;
                }
                else
                {
                    qouteInfo.SellPrice1 = (float)Math.Round(pDepthMarketData.AskPrice1, 3);
                }
                if (pDepthMarketData.AskPrice2 > double.MaxValue / 10 || pDepthMarketData.AskPrice2 < double.MinValue / 10)
                {
                    qouteInfo.SellPrice2 = 0;
                }
                else
                {
                    qouteInfo.SellPrice2 = (float)Math.Round(pDepthMarketData.AskPrice2, 3);
                }
                if (pDepthMarketData.AskPrice3 > double.MaxValue / 10 || pDepthMarketData.AskPrice3 < double.MinValue / 10)
                {
                    qouteInfo.SellPrice3 = 0;
                }
                else
                {
                    qouteInfo.SellPrice3 = (float)Math.Round(pDepthMarketData.AskPrice3, 3);
                }
                if (pDepthMarketData.AskPrice4 > double.MaxValue / 10 || pDepthMarketData.AskPrice4 < double.MinValue / 10)
                {
                    qouteInfo.SellPrice4 = 0;
                }
                else
                {
                    qouteInfo.SellPrice4 = (float)Math.Round(pDepthMarketData.AskPrice4, 3);
                }
                if (pDepthMarketData.AskPrice5 > double.MaxValue / 10 || pDepthMarketData.AskPrice5 < double.MinValue / 10)
                {
                    qouteInfo.SellPrice5 = 0;
                }
                else
                {
                    qouteInfo.SellPrice5 = (float)Math.Round(pDepthMarketData.AskPrice5, 3);
                }

                qouteInfo.SellVol1 = (float)pDepthMarketData.AskVolume1;
                qouteInfo.SellVol2 = (float)pDepthMarketData.AskVolume2;
                qouteInfo.SellVol3 = (float)pDepthMarketData.AskVolume3;
                qouteInfo.SellVol4 = (float)pDepthMarketData.AskVolume4;
                qouteInfo.SellVol5 = (float)pDepthMarketData.AskVolume5;
                #endregion

                #region LastPrice
                if (pDepthMarketData.LastPrice > double.MaxValue / 10 || pDepthMarketData.LastPrice < double.MinValue / 10)
                {
                    qouteInfo.LastPrice = 0;
                }
                else
                {
                    qouteInfo.LastPrice = (float)Math.Round(pDepthMarketData.LastPrice, 3);
                }
                #endregion

                #region High
                if (pDepthMarketData.HighestPrice > double.MaxValue / 10 || pDepthMarketData.HighestPrice < double.MinValue / 10)
                {
                    qouteInfo.High = 0;
                }
                else
                {
                    qouteInfo.High = (float)Math.Round(pDepthMarketData.HighestPrice, 3);
                }
                #endregion

                #region Low
                if (pDepthMarketData.LowestPrice > double.MaxValue / 10 || pDepthMarketData.LowestPrice < double.MinValue / 10)
                {
                    qouteInfo.Low = 0;
                }
                else
                {
                    qouteInfo.Low = (float)Math.Round(pDepthMarketData.LowestPrice, 3);
                }
                #endregion

                #region Open
                if (pDepthMarketData.OpenPrice > double.MaxValue / 10 || pDepthMarketData.OpenPrice < double.MinValue / 10)
                {
                    qouteInfo.Open = 0;
                }
                else
                {
                    qouteInfo.Open = (float)Math.Round(pDepthMarketData.OpenPrice, 3);
                }
                #endregion

                #region PriceChange
                if (pDepthMarketData.LastPrice == 0)
                {
                    qouteInfo.PriceChange = 0;
                }
                else
                {
                    qouteInfo.PriceChange = (float)Math.Round(pDepthMarketData.LastPrice - pDepthMarketData.PreClosePrice, 3);
                }
                #endregion

                #region PriceChangePct
                if (pDepthMarketData.PreClosePrice == 0)
                {
                    qouteInfo.PriceChangePct = 0;
                }
                else
                {
                    qouteInfo.PriceChangePct = (float)Math.Round(qouteInfo.PriceChange / qouteInfo.PrevClose, 3);
                }

                #endregion

                #region SettlementPrice
                if (pDepthMarketData.SettlementPrice > double.MaxValue / 10 || pDepthMarketData.SettlementPrice < double.MinValue / 10)
                {
                    qouteInfo.SettlementPrice = 0;
                }
                else
                {
                    qouteInfo.SettlementPrice = (float)Math.Round(pDepthMarketData.SettlementPrice, 3);
                }
                #endregion

                #region PrevClose
                if (pDepthMarketData.PreClosePrice > double.MaxValue / 10 || pDepthMarketData.PreClosePrice < double.MinValue / 10)
                {
                    qouteInfo.PrevClose = 0;
                }
                else
                {
                    qouteInfo.PrevClose = (float)Math.Round(pDepthMarketData.PreClosePrice, 3);
                }
                #endregion

                #region PrevPosition
                qouteInfo.PrevPosition = (float)Math.Round(pDepthMarketData.PreOpenInterest, 3);

                #endregion

                #region PrevSettlementPrice
                if (pDepthMarketData.PreSettlementPrice > double.MaxValue / 10 || pDepthMarketData.PreSettlementPrice < double.MinValue / 10)
                {
                    qouteInfo.PrevSettlementPrice = 0;
                }
                else
                {
                    qouteInfo.PrevSettlementPrice = (float)Math.Round(pDepthMarketData.PreSettlementPrice, 3);
                }
                #endregion

                #endregion

                // 发送回推
                ResponseManager.Instance.OnQoute(qouteInfo);
            }
            catch (Exception ex)
            {
                Logger.Instance.WriteInfo("未处理的异常，" + ex.Message + "\r\n" + ex.InnerException + "\r\n" + ex.StackTrace);
            }
        }

        #endregion
    }
}
